/*--------------------------+
|	   Emitter Class		|
|	---------------------	|
|	Emitter contain and		|
|	emit Particles, also	|
|	managing their data		|
|		and memory.			|
+--------------------------*/

#include <Windows.h>
#include "Emitter.h"
#include "Particle.h"
#include "tinyxml.h"
#include "SGD Wrappers\CSGD_TextureManager.h"

// Renders this emitter's particles
void Emitter::Render(void) const{
	for( uint i = 0; i < Particles.size(); ++i )
		Particles[i]->Render();

	CSGD_Direct3D::GetInstance()->GetSprite()->Flush();

	CSGD_Direct3D::GetInstance()->GetDirect3DDevice()->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
	CSGD_Direct3D::GetInstance()->GetDirect3DDevice()->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);
}

// Update emitter and all of it's particles
void Emitter::Update(float elapsedTime)
{
	for( uint i = 0; i < Particles.size(); ++i )
	{
		Particles[i]->Update(elapsedTime);

		// Destroy the particle if it is finished
		if( Particles[i]->IsFinished() )
		{
			delete Particles[i];
			Particles.erase(Particles.begin() + i);
		}
	}

	// Make particles if it's looping
	if( Particles.size() < MaxParticles && Looping )
	{
		EmissionTimer -= elapsedTime;
		if( EmissionTimer <= 0 )
		{
			for( uint i = 0; i < EmissionRate; ++i )
			{
				Particle* p = new Particle(*MasterParticle);

				p->SetPosition(Position);
				p->RandomizeLifetime(LifetimeRange);
				p->RandomizeRotation(RotationRange);
				p->RandomizeRotationSpeed(RotationSpeedRange);
				p->RandomizeScale(ScaleRange);
				p->RandomizeVelocity(VelocityRange);
				p->RandomizePosition(XRange,YRange);

				Particles.push_back(p);
			}
			EmissionTimer = EmissionDelay;
		}
	}

	// Control the burst
	if( Particles.size() < BurstSize && Bursting )
	{
		EmissionTimer -= elapsedTime;
		if( EmissionTimer <= 0 )
		{
			for( uint i = 0; i < EmissionRate; ++i )
			{
				Particle* p = new Particle(*MasterParticle);

				p->SetPosition(Position);
				p->RandomizeLifetime(LifetimeRange);
				p->RandomizeRotation(RotationRange);
				p->RandomizeRotationSpeed(RotationSpeedRange);
				p->RandomizeScale(ScaleRange);
				p->RandomizeVelocity(VelocityRange);
				p->RandomizePosition(XRange,YRange);

				Particles.push_back(p);
			}

			if( Particles.size() >= BurstSize )
				Bursting = false;

			EmissionTimer = EmissionDelay;
		}
	}

	Particles.shrink_to_fit();
}

// Constructor
Emitter::Emitter(int shape, tVector2D pos, Particle* master, uint min, uint max, float liferange, float scalerange, float xrange, float yrange, float velrange, float rotrange, float rotspeedrange, float emissiondelay, uint emissionrate)
{
	Shape = shape;
	Position = pos;
	MasterParticle = master;
	MinParticles = min;
	MaxParticles = max;
	LifetimeRange = liferange;
	ScaleRange = scalerange;
	XRange = xrange;
	YRange = yrange;
	VelocityRange = velrange;
	RotationRange = rotrange;
	RotationSpeedRange = rotspeedrange;
	Looping = false;
	EmissionDelay = emissiondelay;
	EmissionTimer = emissiondelay;
	EmissionRate = emissionrate;

	Bursting = false;
	BurstSize = 0;
}

// Activate the emitter
void Emitter::Burst(void)
{
	BurstSize = rand() % (MaxParticles - MinParticles) + MinParticles + 1;
	Bursting = true;
}

// Shutdown
void Emitter::Shutdown(void)
{
	for( uint i = 0; i < Particles.size(); ++i )
	{
		// Destroy the particle
		delete Particles[i];
		Particles.erase(Particles.begin() + i);
	}

	// Clean up the image used
	CSGD_TextureManager::GetInstance()->UnloadTexture(MasterParticle->GetImageID());

	// This deletes the master particle
	delete MasterParticle;
}

// Set the Position
void Emitter::SetPosition(float x, float y)
{
	Position.fX = x;
	Position.fY = y;
}

// Load emitter from XML
Emitter* Emitter::LoadEmitter(const char* filename)
{
	Emitter* e = NULL;

	TiXmlDocument doc;
	if( doc.LoadFile(filename) == true )
	{

		TiXmlElement* root = doc.RootElement();

		if( root != NULL )
		{

			TiXmlElement* emitter = root->FirstChildElement("Emitter");

			// Declare vars
			std::string filenames;
			int image = -1;
			float lifespan = 0;
			DWORD color = 0;
			DWORD endcolor = 0;
			DWORD alphacolor = 0;
			float scale = 0;
			float endscale = 0;
			tVector2D position = {0,0};
			tVector2D direction = {0,0};
			float velocity = 0;
			float rotation = 0;
			float rotationspeed = 0;
			D3DBLEND source = D3DBLEND_ZERO;
			D3DBLEND dest = D3DBLEND_ZERO;
			int shape = 0;
			tVector2D eposition = {0,0};
			uint min = 0;
			uint max = 0;
			float liferange = 0;
			float scalerange = 0;
			float xrange = 0;
			float yrange = 0;
			float velrange = 0;
			float rotrange = 0;
			float rotspeedrange = 0;
			float emissiondelay = 0;
			uint emissionrate = 1;


			if( emitter != NULL )
			{
				// Some temp vars to use with the XML Attributes
				double dtemp;
				int itemp;

				// Get the image filename
				filenames = "Graphics/";
				filenames.append(emitter->GetText());

				// Get the particle lifespan
				emitter->Attribute("Lifespan",&dtemp);
				lifespan = (float)dtemp;

				// Get the particle colors
				emitter->Attribute("StartColor",&dtemp);
				color = (DWORD)dtemp;
				emitter->Attribute("EndColor",&dtemp);
				endcolor = (DWORD)dtemp;
				emitter->Attribute("AlphaColor",&dtemp);
				alphacolor = (DWORD)dtemp;

				// Get the scaling
				emitter->Attribute("StartScale",&dtemp);
				scale = (float)dtemp;
				emitter->Attribute("EndScale",&dtemp);
				endscale = (float)dtemp;

				// Get the direction
				emitter->Attribute("XDirection",&dtemp);
				direction.fX = (float)dtemp;
				emitter->Attribute("YDirection",&dtemp);
				direction.fY = (float)dtemp;

				// Get the velocity
				emitter->Attribute("Velocity",&dtemp);
				velocity = (float)dtemp;

				// Get Rotation
				emitter->Attribute("Rotation",&dtemp);
				rotation = (float)dtemp;

				// Get RotationSpeed
				emitter->Attribute("RotationSpeed",&dtemp);
				rotationspeed = (float)dtemp;

				// Get the Blend Mode
				emitter->Attribute("SourceBlend",&itemp);
				source = (D3DBLEND)itemp;
				emitter->Attribute("DestBlend",&itemp);
				dest = (D3DBLEND)itemp;

				// Get the shape of the emitter
				emitter->Attribute("Shape",&shape);

				// Get the min and max of the emitter
				emitter->Attribute("Min",&itemp);
				min = (uint)itemp;
				emitter->Attribute("Max",&itemp);
				max = (uint)itemp;

				// Get the ranges of the particle values
				emitter->Attribute("LifeRange",&dtemp);
				liferange = (float)dtemp;
				emitter->Attribute("ScaleRange",&dtemp);
				scalerange = (float)dtemp;
				emitter->Attribute("XRange",&dtemp);
				xrange = (float)dtemp;
				emitter->Attribute("YRange",&dtemp);
				yrange = (float)dtemp;
				emitter->Attribute("VelRange",&dtemp);
				velrange = (float)dtemp;
				emitter->Attribute("RotRange",&dtemp);
				rotrange = (float)dtemp;
				emitter->Attribute("RotSpeedRange",&dtemp);
				rotspeedrange = (float)dtemp;

				// Get the emission rate
				emitter->Attribute("EmissionDelay",&dtemp);
				emissiondelay = (float)dtemp;
				emitter->Attribute("EmissionRate",&itemp);
				emissionrate = (uint)itemp;
			}

			WCHAR tmpW[100];
			mbstowcs_s(nullptr,tmpW,filenames.c_str(),100);

			image = CSGD_TextureManager::GetInstance()->LoadTexture(tmpW,alphacolor);

			Particle* p = new Particle(image,lifespan,color,endcolor,scale,endscale,position,direction,velocity,rotation,rotationspeed,source,dest);
			e = new Emitter(shape,eposition,p,min,max,liferange,scalerange,xrange,yrange,velrange,rotrange,rotspeedrange,emissiondelay,emissionrate);

		}
	}

	return e;
}